﻿
using System;

namespace LxCFD
{
    public struct VtuCell
    {
        public int[] Connect;
        public int OffSet;
        public uint Type;
        public bool AddCellInf_bound(ref FvCell fvCell, FvFace[] faces, ref int iniOffset)
        {
            ref FvFace face = ref faces[fvCell.NFaces[0]];
            switch (face.NodeIDs.Length)
            {
                case 0:
                case 1:
                case 2:
                    return false;
                case 3:
                    Type = 5;
                    break;
                case 4:
                    Type = 9;
                    break;
                default:
                    Type = 7;
                    break;
            }
            Connect = new int[face.NodeIDs.Length];
            iniOffset += face.NodeIDs.Length;
            OffSet = iniOffset;
            Array.Copy(face.NodeIDs, Connect, Connect.Length);
            return true;
        }
        public bool AddCellInf_inner(ref FvCell fvCell, FvFace[] faces, ref int iniOffset)
        {
            int faceCount = fvCell.OFaces.Length + fvCell.NFaces.Length;
            if (faceCount == 4)
            {
                Connect = new int[4];
                iniOffset += 4;
                OffSet = iniOffset;
                Type = 10;
                int nodeflag = 0;
                foreach (var f in fvCell.OFaces)
                {
                    ref FvFace fvFace = ref faces[f];
                    if (fvFace.NodeIDs.Length != 3) return false;
                    if (nodeflag == 0)
                    {
                        AddFirstFace_Reverse(ref fvFace,ref nodeflag);
                    }
                    else
                    {
                        AddFace_3Nodes(ref fvFace , ref nodeflag);
                    }
                }
                foreach (var f in fvCell.NFaces)
                {
                    ref FvFace fvFace = ref faces[f];
                    if (fvFace.NodeIDs.Length != 3) return false;
                    if (nodeflag == 0)
                    {
                        AddFirstFace_Forward(ref fvFace,ref nodeflag);
                    }
                    else 
                    {
                        AddFace_3Nodes(ref fvFace, ref nodeflag);
                    }
                }
            }
            else if (faceCount == 6)
            {
                Connect = new int[8];
                iniOffset += 8;
                OffSet = iniOffset;
                Type = 12;
                int nodeflag = 0;
                foreach (var f in fvCell.OFaces)
                {
                    ref FvFace fvFace = ref faces[f];
                    if (fvFace.NodeIDs.Length != 4) return false;
                    if (nodeflag == 0)
                    {
                        AddFirstFace_Reverse(ref fvFace,ref nodeflag);
                    }
                    else
                    {
                        AddFace_4Nodes(ref fvFace);
                    }
                }
                foreach (var f in fvCell.NFaces)
                {
                    ref FvFace fvFace = ref faces[f];
                    if (fvFace.NodeIDs.Length != 4) return false;
                    if (nodeflag == 0)
                    {
                        AddFirstFace_Forward(ref fvFace,ref nodeflag);
                    }
                    else
                    {
                        AddFace_4Nodes(ref fvFace);
                    }
                }
            }
            else
            {
                return false;
            }
            return true;

        }
 
        private void AddFirstFace_Forward(ref FvFace face,ref int nodeFlag)
        {
            nodeFlag = face.NodeIDs.Length;
            for (int i1 = 0; i1 < nodeFlag; ++i1)
            {
                Connect[i1] = face.NodeIDs[i1];
            } 
        }
        private void AddFirstFace_Reverse(ref FvFace face, ref int nodeFlag)
        {
            nodeFlag = face.NodeIDs.Length;
            for (int i1 = 0; i1 < nodeFlag; ++i1)
            {
                Connect[i1] = face.NodeIDs[nodeFlag - i1 - 1];
            }
        }
        private void AddFace_3Nodes(ref FvFace face, ref int nodeflag)
        {
            if (nodeflag == 4) return;
            foreach (var n in face.NodeIDs)
            {
                if (n != Connect[0] && n != Connect[1] && n != Connect[2])
                {
                    Connect[3] = n;
                    nodeflag = 4;
                    return;
                }
            }
        }

        private void AddFace_4Nodes(ref FvFace face)
        {
            int lastOne = InConnect(face.NodeIDs[0]);
            for (int i1 = 1; i1 < 4; i1++)
            {
                int thisOne = InConnect(face.NodeIDs[i1]);
                if (lastOne < 0 && thisOne >= 0)
                {
                    Connect[thisOne + 4] = face.NodeIDs[i1 - 1];
                }
                else if (lastOne >= 0 && thisOne < 0)
                {
                    Connect[lastOne + 4] = face.NodeIDs[i1];
                }
                lastOne = thisOne;
            }
            {
                int thisOne = InConnect(face.NodeIDs[0]);
                if (lastOne < 0 && thisOne >= 0)
                {
                    Connect[thisOne + 4] = face.NodeIDs[3];
                }
                else if (lastOne >= 0 && thisOne < 0)
                {
                    Connect[lastOne + 4] = face.NodeIDs[0];
                }
            }
        }
        private int InConnect(int nodeID)
        {
            for (int i2 = 0; i2 < 4; i2++)
            {
                if (nodeID == Connect[i2])
                {
                    return i2;
                }
            }
            return -1;
        }

 
    }
}
//private void AddFace_4_OFace(ref FvFace face, ref int nodeflag)
//{
//    if (nodeflag == 0)
//    {
//        connectivity[0] = face.NodeIDs[0];
//        connectivity[1] = face.NodeIDs[3];
//        connectivity[2] = face.NodeIDs[2];
//        connectivity[3] = face.NodeIDs[1];
//        nodeflag = 4;
//    }
//    else
//    {
//        AddFace_4_common(ref face);
//    }
//}
//private void AddFace_4_NFace(ref FvFace face, ref int nodeflag)
//{
//    if (nodeflag == 0)
//    {
//        connectivity[0] = face.NodeIDs[0];
//        connectivity[1] = face.NodeIDs[1];
//        connectivity[2] = face.NodeIDs[2];
//        connectivity[3] = face.NodeIDs[3];
//        nodeflag = 4;
//    }
//    else
//    {
//        AddFace_4_common(ref face);
//    }
//}